package cn.turboinfo.fuyang.api.domain.common.handler.staff;


import cn.turboinfo.fuyang.api.domain.common.service.company.HousekeepingCompanyService;
import cn.turboinfo.fuyang.api.domain.common.service.division.DivisionService;
import cn.turboinfo.fuyang.api.domain.common.service.file.FileAttachmentService;
import cn.turboinfo.fuyang.api.domain.common.service.site.SiteUrlService;
import cn.turboinfo.fuyang.api.domain.util.PhoneUtils;
import cn.turboinfo.fuyang.api.domain.util.SecurityUtils;
import cn.turboinfo.fuyang.api.domain.util.UsernameUtils;
import cn.turboinfo.fuyang.api.domain.web.component.file.FileRefTypeConstant;
import cn.turboinfo.fuyang.api.entity.common.pojo.company.HousekeepingCompany;
import cn.turboinfo.fuyang.api.entity.common.pojo.division.Division;
import cn.turboinfo.fuyang.api.entity.common.pojo.file.FileAttachment;
import cn.turboinfo.fuyang.api.entity.common.pojo.staff.HousekeepingStaff;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.*;

@RequiredArgsConstructor
@Component
public class StaffDataFactory {

    private final HousekeepingCompanyService housekeepingCompanyService;

    private final DivisionService divisionService;

    private final FileAttachmentService fileAttachmentService;

    private final SiteUrlService siteUrlService;

    @Value("${kit.security.rsa.public-key:}")
    private String base64RSAPublicKey;

    public void assembleCompany(List<HousekeepingStaff> staffList) {

        Set<Long> companyIdSet = staffList.stream()
                .map(HousekeepingStaff::getCompanyId)
                .collect(Collectors.toSet());

        Map<Long, HousekeepingCompany> companyMap = housekeepingCompanyService.findByIdCollection(companyIdSet)
                .stream()
                .collect(Collectors.toMap(HousekeepingCompany::getId, Function.identity()));

        staffList
                .stream()
                .peek(it -> {
                    if (companyMap.containsKey(it.getCompanyId())) {
                        it.setCompanyName(companyMap.get(it.getCompanyId()).getName());
                    }
                })
                .toList();
    }

    public HousekeepingStaff assembleCompany(HousekeepingStaff staff) {

        HousekeepingCompany company = housekeepingCompanyService.getByIdEnsure(staff.getCompanyId());

        staff.setCompanyName(company.getName());
        return staff;
    }

    public void assembleCityName(List<HousekeepingStaff> staffList) {
        Set<Long> provinceCodeSet = staffList.stream()
                .map(HousekeepingStaff::getProvinceCode)
                .collect(Collectors.toSet());

        val divisionMap = divisionService.findByIdCollection(provinceCodeSet)
                .stream()
                .collect(Collectors.toMap(Division::getId, Function.identity()));


        staffList.stream()
                .peek(it -> {
                    if (divisionMap.containsKey(it.getProvinceCode())) {
                        it.setProvinceName(divisionMap.get(it.getProvinceCode()).getAreaName());
                    }
                })
                .toList();
    }

    public HousekeepingStaff assembleCityName(HousekeepingStaff staff) {

        val division = divisionService.getByIdEnsure(staff.getProvinceCode());

        staff.setProvinceName(division.getAreaName());
        return staff;
    }

    public void assembleAttachment(List<HousekeepingStaff> staffList) {
        Set<Long> staffIdSet = staffList.stream()
                .map(HousekeepingStaff::getId)
                .collect(Collectors.toSet());

        // 身份证
        List<FileAttachment> idCardAttachmentList = fileAttachmentService.findByRefIdInAndRefType(staffIdSet, FileRefTypeConstant.STAFF_ATTACH)
                .stream()
                .peek(it -> it.setExternalUrl(siteUrlService.getUploadExternalImgUrl(it.getRelativePath())))
                .toList();

        // 身份证名称集合
        Map<Long, List<String>> idCardMap = idCardAttachmentList
                .stream()
                .filter(it -> it.getRefType().equals(FileRefTypeConstant.STAFF_ATTACH))
                .collect(groupingBy(FileAttachment::getRefId, collectingAndThen(toList(), list -> list.stream()
                        .map(FileAttachment::getDisplayName)
                        .collect(toList()))));

        staffList.stream()
                .peek(it -> {
                    // 身份证
                    if (idCardMap.containsKey(it.getId())) {
                        it.setIdCardFileName(idCardMap.get(it.getId()).get(0));
                    }
                })
                .toList();
    }

    public HousekeepingStaff assembleAttachment(HousekeepingStaff staff) {

        // 身份证
        List<FileAttachment> idCardAttachmentList = fileAttachmentService.findByRefIdAndRefType(staff.getId(), FileRefTypeConstant.STAFF_ATTACH)
                .stream()
                .peek(it -> it.setExternalUrl(siteUrlService.getUploadExternalImgUrl(it.getRelativePath())))
                .toList();
        
        staff.setIdCardFileName(idCardAttachmentList.get(0).getDisplayName());
        return staff;
    }

    public void maskInfo(List<HousekeepingStaff> staffList) {
        staffList.stream()
                .peek(this::maskInfo)
                .toList();
    }

    public void maskInfo(HousekeepingStaff staff) {
        staff.setContactMobileEncrypt(SecurityUtils.encodeBase64(SecurityUtils.encryptRSA(staff.getContactMobile().getBytes(), SecurityUtils.decodeBase64(base64RSAPublicKey))));
        staff.setContactMobile(PhoneUtils.maskPhoneNum(staff.getContactMobile()));
        staff.setName(UsernameUtils.maskUsername(staff.getName()));

    }
}
